This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.
Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.
source("tianfengRwrappers.R")
# library(future)
# plan("multiprocess",workers = 8)
CA_dataset2 <- readRDS("CA_dataset2.rds")
CA_dataset1 <- readRDS("CA_dataset1.rds")
human_coronary <- readRDS("human_coronary.rds")
Idents(human_coronary) <- human_coronary$samples
human_coronary <- RenameIdents(human_coronary,'1' = 'sample1','2' = 'sample2','3' = 'sample3','4' = 'sample4')
human_coronary$samples <- Idents(human_coronary)
Idents(human_coronary) <- human_coronary$Classification1
ds2 <- readRDS("ds2.rds")
#sample info
ggsave("dataset2_sampleinfo.svg",plot = umapplot(CA_dataset2, split.by = "sample"),
device = svg, width = 25, height = 5)
ggsave("dataset1_sampleinfo.svg",plot = umapplot(CA_dataset1, split.by = "orig.ident"),
device = svg, width = 15, height = 5)
ggsave("dataset0_sampleinfo.svg",plot = umapplot(human_coronary, split.by = "samples"),
device = svg, width = 20, height = 5)
ggsave("ds2.svg",plot = umapplot(ds2), device = svg, width = 6, height = 5)
ggsave("ds1.svg",plot = umapplot(ds1), device = svg, width = 6, height = 5)
ggsave("ds0.svg",plot = umapplot(ds1), device = svg, width = 6, height = 5)
附图:所有marker基因表达热图 show 表达量最高的top5
logfc.threshold = 0.5, min.diff.pct = 0.3, pct.1 > 0.7
dataset2
CA_dataset2_markers <- FindAllMarkers(CA_dataset2, logfc.threshold = 0.5, min.diff.pct = 0.3, only.pos = T)
CA_dataset2_markers <- CA_dataset2_markers[CA_dataset2_markers$pct.1>0.7,] %>% group_by(cluster)
genes_to_show <- CA_dataset2_markers %>% group_by(cluster) %>% slice_max(n = 5, order_by = avg_logFC)
svg(paste0("CA_dataset2_supp","_markers.svg"), height = 10, width = 15)
dhm2(CA_dataset2_markers$gene, CA_dataset2, genes_to_show$gene,"CA_dataset2_supp")
dev.off()
dataset1
CA_dataset1_markers <- FindAllMarkers(CA_dataset1, logfc.threshold = 0.5, min.diff.pct = 0.3, only.pos = T)
CA_dataset1_markers <- CA_dataset1_markers[CA_dataset1_markers$pct.1>0.7,] %>% group_by(cluster)
genes_to_show <- CA_dataset1_markers %>% group_by(cluster) %>% slice_max(n = 5, order_by = avg_logFC)
svg(paste0("CA_dataset1_supp","_markers.svg"), height = 10, width = 15)
dhm2(CA_dataset1_markers$gene, CA_dataset1, genes_to_show$gene,"CA_dataset1_supp")
dev.off()
dataset0
human_coronary_markers <- FindAllMarkers(human_coronary, logfc.threshold = 0.5, min.diff.pct = 0.3, only.pos = T)
human_coronary_markers <- human_coronary_markers[human_coronary_markers$pct.1>0.7,] %>% group_by(cluster)
genes_to_show <- human_coronary_markers %>% group_by(cluster) %>% slice_max(n = 5, order_by = avg_logFC)
svg(paste0("human_coronary_supp","_markers.svg"), height = 10, width = 15)
dhm2(human_coronary_markers$gene, human_coronary, genes_to_show$gene,"human_coronary_supp")
dev.off()
样本细胞比例
dataset0 冠状动脉
Idents(human_coronary) <- human_coronary$conditions
sp1 <- subset(human_coronary, idents = "sample1")
sp2 <- subset(human_coronary, idents = "sample2")
sp3 <- subset(human_coronary, idents = "sample3")
sp4 <- subset(human_coronary, idents = "sample4")
prop_mat <- cbind(prop.table(table(sp1$Classification1)),prop.table(table(sp2$Classification1)))
prop_mat2 <- cbind(prop.table(table(sp3$Classification1)),prop.table(table(sp4$Classification1)))
prop_mat <- cbind(prop_mat, prop_mat2)
colnames(prop_mat) <- levels(Idents(human_coronary))
plot_data = melt(prop_mat)
colnames(plot_data) = c('cell type','position','proportion')#修改每一列的名称
ggplot(plot_data, aes(x = `cell type`, y = proportion, fill = position)) +
geom_bar(stat = 'identity', position = "dodge", width=0.5) + theme_bw()
prop_plot <- ggplot(plot_data, aes(x = `cell type`, y = proportion, fill = position)) +
geom_bar(stat = 'identity', position = "dodge", width=0.7) + coord_cartesian(ylim = c(0,0.3))+
theme_bw() + scale_y_continuous(expand = c(0,0)) + scale_fill_manual(values = colors_list[3:6]) +theme(
axis.title.x = element_text(size = 15), axis.text.x = element_text(size = 15, colour = "black"),
axis.title.y = element_text(size = 15), axis.text.y = element_text(size = 15, colour = "black"),
legend.text = element_text(size = 20), legend.title = element_blank(), panel.grid = element_blank())
ggsave("human_coronary_prop.svg", device = svg, plot = prop_plot, width = 12, height = 6)
dataset1 颈动脉
Idents(CA_dataset1) <- CA_dataset1$orig.ident
Idents(CA_dataset1) <- c("sample1","sample2","sample3")
sp1 <- subset(CA_dataset1, idents = "sample1")
sp2 <- subset(CA_dataset1, idents = "sample2")
sp3 <- subset(CA_dataset1, idents = "sample3")
prop_mat <- cbind(prop.table(table(sp1$Classification1)),prop.table(table(sp2$Classification1)),prop.table(table(sp3$Classification1)))
colnames(prop_mat) <- levels(Idents(CA_dataset1))
plot_data = melt(prop_mat)
colnames(plot_data) = c('cell type','position','proportion')#修改每一列的名称
prop_plot <- ggplot(plot_data, aes(x = `cell type`, y = proportion, fill = position)) +
geom_bar(stat = 'identity', position = "dodge", width=0.7) + coord_cartesian(ylim = c(0,0.6))+
theme_bw() + scale_y_continuous(expand = c(0,0)) + scale_fill_manual(values = colors_list[3:6]) +theme(
axis.title.x = element_text(size = 15), axis.text.x = element_text(size = 15, colour = "black"),
axis.title.y = element_text(size = 15), axis.text.y = element_text(size = 15, colour = "black"),
legend.text = element_text(size = 20), legend.title = element_blank(), panel.grid = element_blank())
ggsave("CA_dataset1_prop.svg", device = svg, plot = prop_plot, width = 12, height = 6)
dataset2 颈动脉
Idents(CA_dataset2) <- factor(CA_dataset2$sample,levels = c("AC_1","AC_2","AC_3","PA_1","PA_2","PA_3"))
sp1 <- subset(CA_dataset2, idents = "AC_1")
sp2 <- subset(CA_dataset2, idents = "AC_2")
sp3 <- subset(CA_dataset2, idents = "AC_3")
sp4 <- subset(CA_dataset2, idents = "PA_1")
sp5 <- subset(CA_dataset2, idents = "PA_2")
sp6 <- subset(CA_dataset2, idents = "PA_3")
prop_mat <- cbind(prop.table(table(sp1$Classification1)),prop.table(table(sp2$Classification1)),
prop.table(table(sp3$Classification1)),prop.table(table(sp4$Classification1)),
prop.table(table(sp5$Classification1)),prop.table(table(sp6$Classification1)))
colnames(prop_mat) <- levels(Idents(CA_dataset2))
plot_data = melt(prop_mat)
colnames(plot_data) = c('cell type','position','proportion')#修改每一列的名称
prop_plot <- ggplot(plot_data, aes(x = `cell type`, y = proportion, fill = position)) +
geom_bar(stat = 'identity', position = "dodge", width=0.7) + coord_cartesian(ylim = c(0,0.6))+
theme_bw() + scale_y_continuous(expand = c(0,0)) + scale_fill_manual(values = colors_list[3:8]) +theme(
axis.title.x = element_text(size = 15), axis.text.x = element_text(size = 15, colour = "black"),
axis.title.y = element_text(size = 15), axis.text.y = element_text(size = 15, colour = "black"),
legend.text = element_text(size = 20), legend.title = element_blank(), panel.grid = element_blank())
ggsave("CA_dataset2_prop.svg", device = svg, plot = prop_plot, width = 16, height = 6)
XGBoost feature plot
pretrain AC–PA
fea <- read.csv("./datatable/AC_features.csv")
ggobj <- multi_featureplot(fea$Feature[1:16],ds2_AC,labels = "",label = F)
ggsave("ACpretrain_features.png", device = png, plot = ggobj, width = 8, height = 8)
fea <- read.csv("./datatable/PA_features.csv")
ggobj <- multi_featureplot(fea$Feature[1:16],ds2_PA,labels = "",label = F)
ggsave("PApretrain_features.png", device = png, plot = ggobj, width = 8, height = 8)
model AC–PA
fea <- read.csv("./datatable/ACtrain_features.csv")
ggobj <- multi_featureplot(fea$Feature[1:16],ds2_AC,labels = "",label = F)
ggsave("./supp/ACmodel_features.png", device = png, plot = ggobj, width = 10, height = 8)
fea <- read.csv("./datatable/PAtrain_features.csv")
ggobj <- multi_featureplot(fea$Feature[1:16],ds2_PA,labels = "",label = F)
ggsave("./supp/PAmodel_features.png", device = png, plot = ggobj, width = 10, height = 8)
model ds2
fea <- read.csv("./datatable/ds2_features.csv")
ggobj <- multi_featureplot(fea$Feature[1:16],ds2,labels = "",label = F)
ggsave("ds2model_features.png", device = png, plot = ggobj, width = 8, height = 8)
fea <- read.csv("./datatable/ds0_features.csv")
ggobj <- multi_featureplot(fea$Feature[1:16],ds0,labels = "",label = F)
ggsave("ds0model_features.png", device = png, plot = ggobj, width = 8, height = 8)
SMC/marker features in SMC2
Idents(ds2) <- ds2$Classification1
ds2_SMC2 <- subset(ds2, ident = "SMC2")
data2 <- FetchData(object = ds2_SMC2, vars = c("ACTA2", "TAGLN"))
rownames(data2) <- NULL
data2$group <- "unsup"
ggplot(data2, aes(x=ACTA2, y=TAGLN, color = group, group = group)) +
geom_point(size = 3,alpha=0.1) +
geom_smooth(method=lm , color="red", fill="#69b3a2", formula = 'y~x', se=TRUE) +
theme_classic() + theme(axis.title = element_text(size = 20,color = "black"),
axis.text = element_text(size = 20,color = "black"),
axis.line = element_line(size = 1),
axis.ticks = element_line(size = 1),
title = element_text(size = 20)) # 781 ACTA+ TAGLN+ in 792 ACTA+
data2 <- FetchData(object = ds2_SMC2, vars = c("SOST", "DLX5"))
rownames(data2) <- NULL
data2$group <- "unsup"
ggplot(data2, aes(x=SOST, y=DLX5, color = group, group = group)) +
geom_point(size = 3,alpha=0.1) +
geom_smooth(method=lm , color="red", fill="#69b3a2", formula = 'y~x', se=TRUE) +
theme_classic() + theme(axis.title = element_text(size = 20,color = "black"),
axis.text = element_text(size = 20,color = "black"),
axis.line = element_line(size = 1),
axis.ticks = element_line(size = 1),
title = element_text(size = 20))
data2 <- FetchData(object = ds2_SMC2, vars = c("DLX6-AS1", "DLX5"))
rownames(data2) <- NULL
data2$group <- "unsup"
ggplot(data2, aes(x=`DLX6-AS1`, y=DLX5, color = group, group = group)) +
geom_point(size = 3,alpha=0.1) +
geom_smooth(method=lm , color="red", fill="#69b3a2", formula = 'y~x', se=TRUE) +
theme_classic() + theme(axis.title = element_text(size = 20,color = "black"),
axis.text = element_text(size = 20,color = "black"),
axis.line = element_line(size = 1),
axis.ticks = element_line(size = 1),
title = element_text(size = 20))
# dim(subset(ds2_SMC2, SOST>0))[2]
dim(subset(ds2_SMC2, `DLX5`>1))[2]
dim(subset(ds2_SMC2, `DLX5`>1&SOST>1))[2]
print("...")
dim(subset(ds2_SMC2, DLX5>1))[2]
dim(subset(ds2_SMC2, `PRDM6`>1))[2]
dim(subset(ds2_SMC2, `PRDM6`>1&DLX5>1))[2]
dim(subset(ds2_SMC2, ACTA2>1))[2]
dim(subset(ds2_SMC2, TAGLN>1))[2]
dim(subset(ds2_SMC2, TAGLN>1&ACTA2>1))[2]
GO for neural progenitor in ds2
library(org.Hs.eg.db)
enrich.go <- CA_dataset2_markers[CA_dataset2_markers$cluster == "Neural progenitor",]$gene %>% enrichGO(
OrgDb = org.Hs.eg.db,
keyType = "SYMBOL",
ont = "ALL", # 可选 BP、MF、CC,也可以指定 ALL 同时计算 3 者
pAdjustMethod = "fdr",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
)
plot <- dotplot(enrich.go, title = paste("Neural progenitor", "GO"), showCategory = 15) +
theme_classic() + theme(text = element_text(colour = "black", size = 16),
plot.title = element_text(size = 16,color="black",hjust = 0.5),
axis.title = element_text(size = 16,color ="black"),
axis.text = element_text(size= 16,color = "black"))
ggsave("GO_Neural progenitor.svg",device = svg,height = 6,width = 10, plot = plot)
BMP receptors in different dataset
Dotplot(c("BMPR1B","BMPR1A","BMPR2","ACVR2A"),ds0)
Dotplot(c("BMPR1B","BMPR1A","BMPR2","ACVR2A"),ds1)
Dotplot(c("BMPR1B","BMPR1A","BMPR2","ACVR2A"),ds2)
Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.
When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).
The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAoKYGBge3J9CnNvdXJjZSgidGlhbmZlbmdSd3JhcHBlcnMuUiIpCiMgbGlicmFyeShmdXR1cmUpIAojIHBsYW4oIm11bHRpcHJvY2VzcyIsd29ya2VycyA9IDgpCmBgYAoKYGBge3J9CkNBX2RhdGFzZXQyIDwtIHJlYWRSRFMoIkNBX2RhdGFzZXQyLnJkcyIpCkNBX2RhdGFzZXQxIDwtIHJlYWRSRFMoIkNBX2RhdGFzZXQxLnJkcyIpCmh1bWFuX2Nvcm9uYXJ5IDwtIHJlYWRSRFMoImh1bWFuX2Nvcm9uYXJ5LnJkcyIpCklkZW50cyhodW1hbl9jb3JvbmFyeSkgPC0gaHVtYW5fY29yb25hcnkkc2FtcGxlcwpodW1hbl9jb3JvbmFyeSA8LSBSZW5hbWVJZGVudHMoaHVtYW5fY29yb25hcnksJzEnID0gJ3NhbXBsZTEnLCcyJyA9ICdzYW1wbGUyJywnMycgPSAnc2FtcGxlMycsJzQnID0gJ3NhbXBsZTQnKQpodW1hbl9jb3JvbmFyeSRzYW1wbGVzIDwtIElkZW50cyhodW1hbl9jb3JvbmFyeSkKSWRlbnRzKGh1bWFuX2Nvcm9uYXJ5KSA8LSBodW1hbl9jb3JvbmFyeSRDbGFzc2lmaWNhdGlvbjEKZHMyIDwtIHJlYWRSRFMoImRzMi5yZHMiKQpgYGAKCiNzYW1wbGUgaW5mbwpgYGB7cn0KZ2dzYXZlKCJkYXRhc2V0Ml9zYW1wbGVpbmZvLnN2ZyIscGxvdCA9IHVtYXBwbG90KENBX2RhdGFzZXQyLCBzcGxpdC5ieSA9ICJzYW1wbGUiKSwgCiAgICAgICBkZXZpY2UgPSBzdmcsIHdpZHRoID0gMjUsIGhlaWdodCA9IDUpCmdnc2F2ZSgiZGF0YXNldDFfc2FtcGxlaW5mby5zdmciLHBsb3QgPSB1bWFwcGxvdChDQV9kYXRhc2V0MSwgc3BsaXQuYnkgPSAib3JpZy5pZGVudCIpLAogICAgICAgZGV2aWNlID0gc3ZnLCB3aWR0aCA9IDE1LCBoZWlnaHQgPSA1KQpnZ3NhdmUoImRhdGFzZXQwX3NhbXBsZWluZm8uc3ZnIixwbG90ID0gdW1hcHBsb3QoaHVtYW5fY29yb25hcnksIHNwbGl0LmJ5ID0gInNhbXBsZXMiKSwKICAgICAgIGRldmljZSA9IHN2Zywgd2lkdGggPSAyMCwgaGVpZ2h0ID0gNSkKCmdnc2F2ZSgiZHMyLnN2ZyIscGxvdCA9IHVtYXBwbG90KGRzMiksIGRldmljZSA9IHN2Zywgd2lkdGggPSA2LCBoZWlnaHQgPSA1KQpnZ3NhdmUoImRzMS5zdmciLHBsb3QgPSB1bWFwcGxvdChkczEpLCBkZXZpY2UgPSBzdmcsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNSkKZ2dzYXZlKCJkczAuc3ZnIixwbG90ID0gdW1hcHBsb3QoZHMxKSwgZGV2aWNlID0gc3ZnLCB3aWR0aCA9IDYsIGhlaWdodCA9IDUpCmBgYAoKCiMg6ZmE5Zu+77ya5omA5pyJbWFya2Vy5Z+65Zug6KGo6L6+54Ot5Zu+IHNob3cg6KGo6L6+6YeP5pyA6auY55qEdG9wNQojIyMgbG9nZmMudGhyZXNob2xkID0gMC41LCBtaW4uZGlmZi5wY3QgPSAwLjMsIHBjdC4xID4gMC43CmRhdGFzZXQyCmBgYHtyfQpDQV9kYXRhc2V0Ml9tYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKENBX2RhdGFzZXQyLCBsb2dmYy50aHJlc2hvbGQgPSAwLjUsIG1pbi5kaWZmLnBjdCA9IDAuMywgb25seS5wb3MgPSBUKQpDQV9kYXRhc2V0Ml9tYXJrZXJzIDwtIENBX2RhdGFzZXQyX21hcmtlcnNbQ0FfZGF0YXNldDJfbWFya2VycyRwY3QuMT4wLjcsXSAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgCgpnZW5lc190b19zaG93IDwtIENBX2RhdGFzZXQyX21hcmtlcnMgJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSBzbGljZV9tYXgobiA9IDUsIG9yZGVyX2J5ID0gYXZnX2xvZ0ZDKQoKc3ZnKHBhc3RlMCgiQ0FfZGF0YXNldDJfc3VwcCIsIl9tYXJrZXJzLnN2ZyIpLCBoZWlnaHQgPSAxMCwgd2lkdGggPSAxNSkKZGhtMihDQV9kYXRhc2V0Ml9tYXJrZXJzJGdlbmUsIENBX2RhdGFzZXQyLCBnZW5lc190b19zaG93JGdlbmUsIkNBX2RhdGFzZXQyX3N1cHAiKQpkZXYub2ZmKCkKYGBgCiMjIGRhdGFzZXQxCmBgYHtyfQpDQV9kYXRhc2V0MV9tYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKENBX2RhdGFzZXQxLCBsb2dmYy50aHJlc2hvbGQgPSAwLjUsIG1pbi5kaWZmLnBjdCA9IDAuMywgb25seS5wb3MgPSBUKQpDQV9kYXRhc2V0MV9tYXJrZXJzIDwtIENBX2RhdGFzZXQxX21hcmtlcnNbQ0FfZGF0YXNldDFfbWFya2VycyRwY3QuMT4wLjcsXSAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgCgpnZW5lc190b19zaG93IDwtIENBX2RhdGFzZXQxX21hcmtlcnMgJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSBzbGljZV9tYXgobiA9IDUsIG9yZGVyX2J5ID0gYXZnX2xvZ0ZDKQoKc3ZnKHBhc3RlMCgiQ0FfZGF0YXNldDFfc3VwcCIsIl9tYXJrZXJzLnN2ZyIpLCBoZWlnaHQgPSAxMCwgd2lkdGggPSAxNSkKZGhtMihDQV9kYXRhc2V0MV9tYXJrZXJzJGdlbmUsIENBX2RhdGFzZXQxLCBnZW5lc190b19zaG93JGdlbmUsIkNBX2RhdGFzZXQxX3N1cHAiKQpkZXYub2ZmKCkKYGBgCiMjIGRhdGFzZXQwCmBgYHtyfQpodW1hbl9jb3JvbmFyeV9tYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKGh1bWFuX2Nvcm9uYXJ5LCBsb2dmYy50aHJlc2hvbGQgPSAwLjUsIG1pbi5kaWZmLnBjdCA9IDAuMywgb25seS5wb3MgPSBUKQpodW1hbl9jb3JvbmFyeV9tYXJrZXJzIDwtIGh1bWFuX2Nvcm9uYXJ5X21hcmtlcnNbaHVtYW5fY29yb25hcnlfbWFya2VycyRwY3QuMT4wLjcsXSAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgCgpnZW5lc190b19zaG93IDwtIGh1bWFuX2Nvcm9uYXJ5X21hcmtlcnMgJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSBzbGljZV9tYXgobiA9IDUsIG9yZGVyX2J5ID0gYXZnX2xvZ0ZDKQoKc3ZnKHBhc3RlMCgiaHVtYW5fY29yb25hcnlfc3VwcCIsIl9tYXJrZXJzLnN2ZyIpLCBoZWlnaHQgPSAxMCwgd2lkdGggPSAxNSkKZGhtMihodW1hbl9jb3JvbmFyeV9tYXJrZXJzJGdlbmUsIGh1bWFuX2Nvcm9uYXJ5LCBnZW5lc190b19zaG93JGdlbmUsImh1bWFuX2Nvcm9uYXJ5X3N1cHAiKQpkZXYub2ZmKCkKYGBgCgojIOagt+acrOe7huiDnuavlOS+iwojIyBkYXRhc2V0MCDlhqDnirbliqjohIkKYGBge3J9CklkZW50cyhodW1hbl9jb3JvbmFyeSkgPC0gaHVtYW5fY29yb25hcnkkY29uZGl0aW9ucwpzcDEgPC0gc3Vic2V0KGh1bWFuX2Nvcm9uYXJ5LCBpZGVudHMgPSAic2FtcGxlMSIpCnNwMiA8LSBzdWJzZXQoaHVtYW5fY29yb25hcnksIGlkZW50cyA9ICJzYW1wbGUyIikKc3AzIDwtIHN1YnNldChodW1hbl9jb3JvbmFyeSwgaWRlbnRzID0gInNhbXBsZTMiKQpzcDQgPC0gc3Vic2V0KGh1bWFuX2Nvcm9uYXJ5LCBpZGVudHMgPSAic2FtcGxlNCIpCnByb3BfbWF0IDwtIGNiaW5kKHByb3AudGFibGUodGFibGUoc3AxJENsYXNzaWZpY2F0aW9uMSkpLHByb3AudGFibGUodGFibGUoc3AyJENsYXNzaWZpY2F0aW9uMSkpKQpwcm9wX21hdDIgPC0gY2JpbmQocHJvcC50YWJsZSh0YWJsZShzcDMkQ2xhc3NpZmljYXRpb24xKSkscHJvcC50YWJsZSh0YWJsZShzcDQkQ2xhc3NpZmljYXRpb24xKSkpCnByb3BfbWF0IDwtIGNiaW5kKHByb3BfbWF0LCBwcm9wX21hdDIpCmNvbG5hbWVzKHByb3BfbWF0KSA8LSBsZXZlbHMoSWRlbnRzKGh1bWFuX2Nvcm9uYXJ5KSkKCgpwbG90X2RhdGEgPSBtZWx0KHByb3BfbWF0KQpjb2xuYW1lcyhwbG90X2RhdGEpID0gYygnY2VsbCB0eXBlJywncG9zaXRpb24nLCdwcm9wb3J0aW9uJykj5L+u5pS55q+P5LiA5YiX55qE5ZCN56ewCgpnZ3Bsb3QocGxvdF9kYXRhLCBhZXMoeCA9IGBjZWxsIHR5cGVgLCB5ID0gcHJvcG9ydGlvbiwgZmlsbCA9IHBvc2l0aW9uKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JywgcG9zaXRpb24gPSAiZG9kZ2UiLCB3aWR0aD0wLjUpICsgdGhlbWVfYncoKQoKcHJvcF9wbG90IDwtIGdncGxvdChwbG90X2RhdGEsIGFlcyh4ID0gYGNlbGwgdHlwZWAsIHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gcG9zaXRpb24pKSArIAogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHdpZHRoPTAuNykgKyBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwwLjMpKSsKICB0aGVtZV9idygpICsgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwwKSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnNfbGlzdFszOjZdKSArdGhlbWUoCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LCBjb2xvdXIgPSAiYmxhY2siKSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIGNvbG91ciA9ICJibGFjayIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpKQoKZ2dzYXZlKCJodW1hbl9jb3JvbmFyeV9wcm9wLnN2ZyIsIGRldmljZSA9IHN2ZywgcGxvdCA9IHByb3BfcGxvdCwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNikKCmBgYAoKIyMgZGF0YXNldDEg6aKI5Yqo6ISJCmBgYHtyfQpJZGVudHMoQ0FfZGF0YXNldDEpIDwtIENBX2RhdGFzZXQxJG9yaWcuaWRlbnQKSWRlbnRzKENBX2RhdGFzZXQxKSA8LSBjKCJzYW1wbGUxIiwic2FtcGxlMiIsInNhbXBsZTMiKQoKc3AxIDwtIHN1YnNldChDQV9kYXRhc2V0MSwgaWRlbnRzID0gInNhbXBsZTEiKQpzcDIgPC0gc3Vic2V0KENBX2RhdGFzZXQxLCBpZGVudHMgPSAic2FtcGxlMiIpCnNwMyA8LSBzdWJzZXQoQ0FfZGF0YXNldDEsIGlkZW50cyA9ICJzYW1wbGUzIikKcHJvcF9tYXQgPC0gY2JpbmQocHJvcC50YWJsZSh0YWJsZShzcDEkQ2xhc3NpZmljYXRpb24xKSkscHJvcC50YWJsZSh0YWJsZShzcDIkQ2xhc3NpZmljYXRpb24xKSkscHJvcC50YWJsZSh0YWJsZShzcDMkQ2xhc3NpZmljYXRpb24xKSkpCgpjb2xuYW1lcyhwcm9wX21hdCkgPC0gbGV2ZWxzKElkZW50cyhDQV9kYXRhc2V0MSkpCgpwbG90X2RhdGEgPSBtZWx0KHByb3BfbWF0KQpjb2xuYW1lcyhwbG90X2RhdGEpID0gYygnY2VsbCB0eXBlJywncG9zaXRpb24nLCdwcm9wb3J0aW9uJykj5L+u5pS55q+P5LiA5YiX55qE5ZCN56ewCgpwcm9wX3Bsb3QgPC0gZ2dwbG90KHBsb3RfZGF0YSwgYWVzKHggPSBgY2VsbCB0eXBlYCwgeSA9IHByb3BvcnRpb24sIGZpbGwgPSBwb3NpdGlvbikpICsgCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScsIHBvc2l0aW9uID0gImRvZGdlIiwgd2lkdGg9MC43KSArIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLDAuNikpKwogIHRoZW1lX2J3KCkgKyBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLDApKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yc19saXN0WzM6Nl0pICt0aGVtZSgKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIGNvbG91ciA9ICJibGFjayIpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwgY29sb3VyID0gImJsYWNrIiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkpCgpnZ3NhdmUoIkNBX2RhdGFzZXQxX3Byb3Auc3ZnIiwgZGV2aWNlID0gc3ZnLCBwbG90ID0gcHJvcF9wbG90LCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA2KQpgYGAKCiMjIGRhdGFzZXQyIOmiiOWKqOiEiQpgYGB7cn0KCklkZW50cyhDQV9kYXRhc2V0MikgPC0gZmFjdG9yKENBX2RhdGFzZXQyJHNhbXBsZSxsZXZlbHMgPSBjKCJBQ18xIiwiQUNfMiIsIkFDXzMiLCJQQV8xIiwiUEFfMiIsIlBBXzMiKSkKc3AxIDwtIHN1YnNldChDQV9kYXRhc2V0MiwgaWRlbnRzID0gIkFDXzEiKQpzcDIgPC0gc3Vic2V0KENBX2RhdGFzZXQyLCBpZGVudHMgPSAiQUNfMiIpCnNwMyA8LSBzdWJzZXQoQ0FfZGF0YXNldDIsIGlkZW50cyA9ICJBQ18zIikKc3A0IDwtIHN1YnNldChDQV9kYXRhc2V0MiwgaWRlbnRzID0gIlBBXzEiKQpzcDUgPC0gc3Vic2V0KENBX2RhdGFzZXQyLCBpZGVudHMgPSAiUEFfMiIpCnNwNiA8LSBzdWJzZXQoQ0FfZGF0YXNldDIsIGlkZW50cyA9ICJQQV8zIikKCnByb3BfbWF0IDwtIGNiaW5kKHByb3AudGFibGUodGFibGUoc3AxJENsYXNzaWZpY2F0aW9uMSkpLHByb3AudGFibGUodGFibGUoc3AyJENsYXNzaWZpY2F0aW9uMSkpLAogICAgICAgICAgICAgICAgICBwcm9wLnRhYmxlKHRhYmxlKHNwMyRDbGFzc2lmaWNhdGlvbjEpKSxwcm9wLnRhYmxlKHRhYmxlKHNwNCRDbGFzc2lmaWNhdGlvbjEpKSwKICAgICAgICAgICAgICAgICAgcHJvcC50YWJsZSh0YWJsZShzcDUkQ2xhc3NpZmljYXRpb24xKSkscHJvcC50YWJsZSh0YWJsZShzcDYkQ2xhc3NpZmljYXRpb24xKSkpCgpjb2xuYW1lcyhwcm9wX21hdCkgPC0gbGV2ZWxzKElkZW50cyhDQV9kYXRhc2V0MikpCgpwbG90X2RhdGEgPSBtZWx0KHByb3BfbWF0KQpjb2xuYW1lcyhwbG90X2RhdGEpID0gYygnY2VsbCB0eXBlJywncG9zaXRpb24nLCdwcm9wb3J0aW9uJykj5L+u5pS55q+P5LiA5YiX55qE5ZCN56ewCgpwcm9wX3Bsb3QgPC0gZ2dwbG90KHBsb3RfZGF0YSwgYWVzKHggPSBgY2VsbCB0eXBlYCwgeSA9IHByb3BvcnRpb24sIGZpbGwgPSBwb3NpdGlvbikpICsgCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScsIHBvc2l0aW9uID0gImRvZGdlIiwgd2lkdGg9MC43KSArIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLDAuNikpKwogIHRoZW1lX2J3KCkgKyBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLDApKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yc19saXN0WzM6OF0pICt0aGVtZSgKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIGNvbG91ciA9ICJibGFjayIpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwgY29sb3VyID0gImJsYWNrIiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkpCgpnZ3NhdmUoIkNBX2RhdGFzZXQyX3Byb3Auc3ZnIiwgZGV2aWNlID0gc3ZnLCBwbG90ID0gcHJvcF9wbG90LCB3aWR0aCA9IDE2LCBoZWlnaHQgPSA2KQpgYGAKCiMgWEdCb29zdCBmZWF0dXJlIHBsb3QKIyMgcHJldHJhaW4gQUMtLVBBCmBgYHtyIGZpZy53aWR0aD02LGZpZy5oZWlnaHQ9Nn0KZmVhIDwtIHJlYWQuY3N2KCIuL2RhdGF0YWJsZS9BQ19mZWF0dXJlcy5jc3YiKQpnZ29iaiA8LSBtdWx0aV9mZWF0dXJlcGxvdChmZWEkRmVhdHVyZVsxOjE2XSxkczJfQUMsbGFiZWxzID0gIiIsbGFiZWwgPSBGKQpnZ3NhdmUoIkFDcHJldHJhaW5fZmVhdHVyZXMucG5nIiwgZGV2aWNlID0gcG5nLCBwbG90ID0gZ2dvYmosIHdpZHRoID0gOCwgaGVpZ2h0ID0gOCkKCmZlYSA8LSByZWFkLmNzdigiLi9kYXRhdGFibGUvUEFfZmVhdHVyZXMuY3N2IikKZ2dvYmogPC0gbXVsdGlfZmVhdHVyZXBsb3QoZmVhJEZlYXR1cmVbMToxNl0sZHMyX1BBLGxhYmVscyA9ICIiLGxhYmVsID0gRikKZ2dzYXZlKCJQQXByZXRyYWluX2ZlYXR1cmVzLnBuZyIsIGRldmljZSA9IHBuZywgcGxvdCA9IGdnb2JqLCB3aWR0aCA9IDgsIGhlaWdodCA9IDgpCmBgYAoKIyMjIG1vZGVsIEFDLS1QQQpgYGB7ciBmaWcud2lkdGg9NixmaWcuaGVpZ2h0PTZ9CmZlYSA8LSByZWFkLmNzdigiLi9kYXRhdGFibGUvQUN0cmFpbl9mZWF0dXJlcy5jc3YiKQpnZ29iaiA8LSBtdWx0aV9mZWF0dXJlcGxvdChmZWEkRmVhdHVyZVsxOjE2XSxkczJfQUMsbGFiZWxzID0gIiIsbGFiZWwgPSBGKQpnZ3NhdmUoIi4vc3VwcC9BQ21vZGVsX2ZlYXR1cmVzLnBuZyIsIGRldmljZSA9IHBuZywgcGxvdCA9IGdnb2JqLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA4KQoKZmVhIDwtIHJlYWQuY3N2KCIuL2RhdGF0YWJsZS9QQXRyYWluX2ZlYXR1cmVzLmNzdiIpCmdnb2JqIDwtIG11bHRpX2ZlYXR1cmVwbG90KGZlYSRGZWF0dXJlWzE6MTZdLGRzMl9QQSxsYWJlbHMgPSAiIixsYWJlbCA9IEYpCmdnc2F2ZSgiLi9zdXBwL1BBbW9kZWxfZmVhdHVyZXMucG5nIiwgZGV2aWNlID0gcG5nLCBwbG90ID0gZ2dvYmosIHdpZHRoID0gMTAsIGhlaWdodCA9IDgpCmBgYAoKIyMjIG1vZGVsIGRzMgpgYGB7ciBmaWcud2lkdGg9NixmaWcuaGVpZ2h0PTZ9CmZlYSA8LSByZWFkLmNzdigiLi9kYXRhdGFibGUvZHMyX2ZlYXR1cmVzLmNzdiIpCmdnb2JqIDwtIG11bHRpX2ZlYXR1cmVwbG90KGZlYSRGZWF0dXJlWzE6MTZdLGRzMixsYWJlbHMgPSAiIixsYWJlbCA9IEYpCmdnc2F2ZSgiZHMybW9kZWxfZmVhdHVyZXMucG5nIiwgZGV2aWNlID0gcG5nLCBwbG90ID0gZ2dvYmosIHdpZHRoID0gOCwgaGVpZ2h0ID0gOCkKCmZlYSA8LSByZWFkLmNzdigiLi9kYXRhdGFibGUvZHMwX2ZlYXR1cmVzLmNzdiIpCmdnb2JqIDwtIG11bHRpX2ZlYXR1cmVwbG90KGZlYSRGZWF0dXJlWzE6MTZdLGRzMCxsYWJlbHMgPSAiIixsYWJlbCA9IEYpCmdnc2F2ZSgiZHMwbW9kZWxfZmVhdHVyZXMucG5nIiwgZGV2aWNlID0gcG5nLCBwbG90ID0gZ2dvYmosIHdpZHRoID0gOCwgaGVpZ2h0ID0gOCkKYGBgCgoKCgojIyBTTUMvbWFya2VyIGZlYXR1cmVzIGluIFNNQzIgCmBgYHtyfQpJZGVudHMoZHMyKSA8LSBkczIkQ2xhc3NpZmljYXRpb24xCmRzMl9TTUMyIDwtIHN1YnNldChkczIsIGlkZW50ID0gIlNNQzIiKQoKCmRhdGEyIDwtIEZldGNoRGF0YShvYmplY3QgPSBkczJfU01DMiwgdmFycyA9IGMoIkFDVEEyIiwgIlRBR0xOIikpCnJvd25hbWVzKGRhdGEyKSA8LSAgTlVMTApkYXRhMiRncm91cCA8LSAidW5zdXAiCgpnZ3Bsb3QoZGF0YTIsIGFlcyh4PUFDVEEyLCB5PVRBR0xOLCBjb2xvciA9IGdyb3VwLCBncm91cCA9IGdyb3VwKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsYWxwaGE9MC4xKSArIAogIGdlb21fc21vb3RoKG1ldGhvZD1sbSAsIGNvbG9yPSJyZWQiLCBmaWxsPSIjNjliM2EyIiwgZm9ybXVsYSA9ICd5fngnLCBzZT1UUlVFKSArCiAgdGhlbWVfY2xhc3NpYygpICsgIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCxjb2xvciA9ICJibGFjayIpLAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShzaXplID0gMSksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShzaXplID0gMSksCiAgICAgICAgdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSkgIyA3ODEgQUNUQSsgVEFHTE4rIGluIDc5MiBBQ1RBKyAKCmRhdGEyIDwtIEZldGNoRGF0YShvYmplY3QgPSBkczJfU01DMiwgdmFycyA9IGMoIlNPU1QiLCAiRExYNSIpKQpyb3duYW1lcyhkYXRhMikgPC0gIE5VTEwKZGF0YTIkZ3JvdXAgPC0gInVuc3VwIgoKZ2dwbG90KGRhdGEyLCBhZXMoeD1TT1NULCB5PURMWDUsIGNvbG9yID0gZ3JvdXAsIGdyb3VwID0gZ3JvdXApKSArCiAgZ2VvbV9wb2ludChzaXplID0gMyxhbHBoYT0wLjEpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtICwgY29sb3I9InJlZCIsIGZpbGw9IiM2OWIzYTIiLCBmb3JtdWxhID0gJ3l+eCcsIHNlPVRSVUUpICsKICB0aGVtZV9jbGFzc2ljKCkgKyAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsY29sb3IgPSAiYmxhY2siKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAxKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKHNpemUgPSAxKSwKICAgICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApKQoKZGF0YTIgPC0gRmV0Y2hEYXRhKG9iamVjdCA9IGRzMl9TTUMyLCB2YXJzID0gYygiRExYNi1BUzEiLCAiRExYNSIpKQpyb3duYW1lcyhkYXRhMikgPC0gIE5VTEwKZGF0YTIkZ3JvdXAgPC0gInVuc3VwIgoKZ2dwbG90KGRhdGEyLCBhZXMoeD1gRExYNi1BUzFgLCB5PURMWDUsIGNvbG9yID0gZ3JvdXAsIGdyb3VwID0gZ3JvdXApKSArCiAgZ2VvbV9wb2ludChzaXplID0gMyxhbHBoYT0wLjEpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtICwgY29sb3I9InJlZCIsIGZpbGw9IiM2OWIzYTIiLCBmb3JtdWxhID0gJ3l+eCcsIHNlPVRSVUUpICsKICB0aGVtZV9jbGFzc2ljKCkgKyAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsY29sb3IgPSAiYmxhY2siKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAxKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKHNpemUgPSAxKSwKICAgICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApKQpgYGAKCmBgYHtyfQojIGRpbShzdWJzZXQoZHMyX1NNQzIsIFNPU1Q+MCkpWzJdCgpkaW0oc3Vic2V0KGRzMl9TTUMyLCBgRExYNWA+MSkpWzJdCgpkaW0oc3Vic2V0KGRzMl9TTUMyLCBgRExYNWA+MSZTT1NUPjEpKVsyXQoKcHJpbnQoIi4uLiIpCmRpbShzdWJzZXQoZHMyX1NNQzIsIERMWDU+MSkpWzJdCgpkaW0oc3Vic2V0KGRzMl9TTUMyLCBgUFJETTZgPjEpKVsyXQoKZGltKHN1YnNldChkczJfU01DMiwgYFBSRE02YD4xJkRMWDU+MSkpWzJdCmBgYAoKYGBge3J9CmRpbShzdWJzZXQoZHMyX1NNQzIsIEFDVEEyPjEpKVsyXQoKZGltKHN1YnNldChkczJfU01DMiwgVEFHTE4+MSkpWzJdCgpkaW0oc3Vic2V0KGRzMl9TTUMyLCBUQUdMTj4xJkFDVEEyPjEpKVsyXQpgYGAKCiMgR08gZm9yIG5ldXJhbCBwcm9nZW5pdG9yIGluIGRzMgpgYGB7ciBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Nn0KbGlicmFyeShvcmcuSHMuZWcuZGIpCmVucmljaC5nbyA8LSBDQV9kYXRhc2V0Ml9tYXJrZXJzW0NBX2RhdGFzZXQyX21hcmtlcnMkY2x1c3RlciA9PSAiTmV1cmFsIHByb2dlbml0b3IiLF0kZ2VuZSAlPiUgZW5yaWNoR08oCiAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsCiAgICAgICAga2V5VHlwZSA9ICJTWU1CT0wiLAogICAgICAgIG9udCA9ICJBTEwiLCAjIOWPr+mAiSBCUOOAgU1G44CBQ0PvvIzkuZ/lj6/ku6XmjIflrpogQUxMIOWQjOaXtuiuoeeulyAzIOiAhQogICAgICAgIHBBZGp1c3RNZXRob2QgPSAiZmRyIiwKICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1LAogICAgICAgIHF2YWx1ZUN1dG9mZiA9IDAuMiwKICAgICkKcGxvdCA8LSBkb3RwbG90KGVucmljaC5nbywgdGl0bGUgPSBwYXN0ZSgiTmV1cmFsIHByb2dlbml0b3IiLCAiR08iKSwgc2hvd0NhdGVnb3J5ID0gMTUpICsgCiAgdGhlbWVfY2xhc3NpYygpICsgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMTYpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNixjb2xvcj0iYmxhY2siLGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNixjb2xvciA9ImJsYWNrIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPSAxNixjb2xvciA9ICJibGFjayIpKQpnZ3NhdmUoIkdPX05ldXJhbCBwcm9nZW5pdG9yLnN2ZyIsZGV2aWNlID0gc3ZnLGhlaWdodCA9IDYsd2lkdGggPSAxMCwgcGxvdCA9IHBsb3QpCmBgYAoKIyBCTVAgcmVjZXB0b3JzIGluIGRpZmZlcmVudCBkYXRhc2V0CmBgYHtyfQpEb3RwbG90KGMoIkJNUFIxQiIsIkJNUFIxQSIsIkJNUFIyIiwiQUNWUjJBIiksZHMwKQpEb3RwbG90KGMoIkJNUFIxQiIsIkJNUFIxQSIsIkJNUFIyIiwiQUNWUjJBIiksZHMxKQpEb3RwbG90KGMoIkJNUFIxQiIsIkJNUFIxQSIsIkJNUFIyIiwiQUNWUjJBIiksZHMyKQpgYGAKCgpBZGQgYSBuZXcgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpJbnNlcnQgQ2h1bmsqIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBvciBieSBwcmVzc2luZyAqQ3RybCtBbHQrSSouCgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4KClRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4K